import datetime
import os
import time
import allure
from common.logger import Logger
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.select import Select
from selenium.webdriver.common.action_chains import ActionChains
from selenium import webdriver
from selenium.webdriver.common.keys import Keys#导入键盘操作包

# 封装基本函数 - 执行日志 - 异常处理 - 失败截图
# 所有页面公共的部分
class BasePage:

    def __init__(self,driver):
        self.driver = driver

    # 截图操作
    def save_screenshot(self, doc):
        """  知识点解析      #time strftime() 函数接收以时间元组，并返回以可读字符串表示的当地时间，格式由参数 format 决定。"""
        # 图片名称  页面名称  操作名称   时间  png
        file_path = os.path.abspath(os.path.dirname(os.path.dirname(__file__)) + "/png/{}_{}.png".format(doc,
                                                                    time.strftime("%y%m%d-%H%M%S", time.localtime())))
        try:
            self.driver.save_screenshot(file_path)
            Logger.info("截图成功，文件路径:{}".format(file_path))
            with allure.step(doc):
                allure.attach.file(file_path, doc, allure.attachment_type.PNG)
        except:
            Logger.exception("{}-截图失败！！！".format(doc))

    # 等待元素存在
    def wait_ele_presence(self, locator, center=True, timeout=15, doc=""):
        """     知识点解析：
        #scrollIntoView:
                # 如果为true，元素的顶端将和其所在滚动区的可视区域的顶端对齐。
                # 如果为false，元素的底端将和其所在滚动区的可视区域的底端对齐。
        #scrollIntoViewIfNeeded:
                #如果为true，则元素将在其所在滚动区的可视区域中居中对其。
                # 如果为false，则元素将与其所在滚动区的可视区域最近的边缘对齐。 根据可见区域最靠近元素的哪个边缘，
                # 元素的顶部将与可见区域的顶部边缘对准，或者元素的底部边缘将与可见区域的底部边缘对准。

        #log.exception('exception') #异常信息被自动添加到日志消息中
        #Logger.error(msg[ , *args[ , **kwargs] ] )只记录错误信息"""
        try:
            start = datetime.datetime.now()
            ele = WebDriverWait(self.driver, timeout).until(EC.presence_of_element_located(locator))
            end = datetime.datetime.now()
            Logger.info("{}-元素{}已存在，等待{}秒".format(doc, locator, (end - start).seconds))
            self.driver.execute_script("arguments[0].scrollIntoViewIfNeeded(arguments[1]);", ele, center)
            return ele
        except:
            Logger.exception("{}-元素不存在-{}".format(doc, locator))
            self.save_screenshot("{}-元素不存在".format(doc))
            raise


    # 等待元素可见
    def wait_ele_visible(self, locator, center=True, timeout=15, doc=""):
        self.wait_ele_presence(locator, center, timeout, doc)
        try:
            start = datetime.datetime.now()
            ele = WebDriverWait(self.driver, timeout).until(EC.visibility_of_element_located(locator))
            end = datetime.datetime.now()
            Logger.info("{}-元素{}已可见，等待{}秒".format(doc, locator, (end - start).seconds))
            return ele
        except:
            Logger.exception("{}-元素不可见-{}".format(doc, locator))
            self.save_screenshot("{}-元素不可见".format(doc))
            raise

    # 点击操作
    def click_element(self, locator, center=True, mode=1, timeout=15, doc=""):
        ele = self.wait_ele_visible(locator, center, timeout, doc)
        try:
            with allure.step(doc):
                if mode == 1:
                    ele.click()
                if mode == 2:
                    self.driver.execute_script("arguments[0].click();", ele)
                if mode == 3:
                    ActionChains(self.driver).click(ele).perform()
            Logger.info("{}-元素{}点击成功".format(doc, locator))
        except:
            Logger.exception("{}-元素点击失败-{}".format(doc, locator))
            self.save_screenshot("{}-点击失败".format(doc))
            raise

    # 输入操作
    def input_text(self, locator, text, clear="", center=True, timeout=15, doc=""):
        ele = self.wait_ele_presence(locator, center, timeout, doc)
        try:
            with allure.step(doc):
                if clear == 1:
                    ele.clear()
                elif clear ==  2:
                    ele.send_keys(Keys.CONTROL, "a")
                    ele.send_keys(Keys.DELETE)
                ele.send_keys(text)
            Logger.info("{}-元素{}输入：{}".format(doc, locator, text))
        except:
            Logger.exception("{}-元素输入失败-{}".format(doc, locator))
            self.save_screenshot("{}-输入失败".format(doc))
            raise

    # 下拉框处理
    def select_ele(self, locator, index=None, text=None, value=None, center=True, timeout=15, doc=""):
        ele = self.wait_ele_visible(locator, center, timeout, doc)
        try:
            with allure.step(doc):
                if index:
                    Select(ele).select_by_index(index)
                if text:
                    Select(ele).select_by_visible_text(text)
                if value:
                    Select(ele).select_by_value(value)
            Logger.info("{}-下拉框元素{}选择：index-{}，text-{}，value-{}".format(doc, locator, index, text, value))
        except:
            Logger.exception("{}-元素选择失败-{}".format(doc, locator))
            self.save_screenshot("{}-选择失败".format(doc))
            raise


    # 鼠标悬停
    def hover(self, locator, center=True, timeout=15, doc=""):
        ele = self.wait_ele_presence(locator, center, timeout, doc)
        try:
            with allure.step(doc):
                ActionChains(self.driver).move_to_element(ele).perform()
            Logger.info("{}-元素{}鼠标悬停".format(doc, locator))
        except:
            Logger.exception("{}-元素悬停失败-{}".format(doc, locator))
            self.save_screenshot("{}-鼠标悬停失败".format(doc))
            raise

    # 查找元素
    def get_element(self, locator, doc=""):
        try:
            Logger.info("{}-查找元素：{}".format(doc, locator))
            return self.driver.find_element(*locator)
        except:
            Logger.exception("{}-元素查找失败-{}".format(doc, locator))
            self.save_screenshot("{}-查找失败".format(doc))
            raise

    # 查找匹配元素
    def get_elements(self, locator, doc=""):
        try:
            Logger.info("{}-查找所有匹配的元素：{}".format(doc, locator))
            return self.driver.find_elements(*locator)
        except:
            Logger.exception("{}-元素集查找失败-{}".format(doc, locator))
            self.save_screenshot("{}-查找失败".format(doc))
            raise

    # 获取元素的属性
    def get_ele_attribute(self, locator, name, center=True, timeout=15, doc="获取元素的属性"):
        ele = self.wait_ele_presence(locator, center, timeout, doc)
        try:
            value = ele.get_attribute(name)
            Logger.info("{}-元素{}的{}属性-{}".format(doc, locator, name, value))
            return value
        except:
            Logger.exception("{}-元素获取属性{}失败-{}".format(doc, name, locator))
            self.save_screenshot("{}-获取属性失败".format(doc))
            raise

    # 获取元素的文本内容
    def get_text(self, locator, center=True, timeout=15, doc="获取元素的文本内容"):
        ele = self.wait_ele_presence(locator, center, timeout, doc)
        try:
            text = ele.text
            Logger.info("{}-元素{}的文本内容-{}".format(doc, locator, text))
            return text
        except:
            Logger.exception("{}-元素获取文本失败-{}".format(doc, locator))
            self.save_screenshot("{}-获取文本失败".format(doc))
            raise

    # 获取元素的标签名
    def get_tag_name(self, locator, center=True, timeout=15, doc="获取元素的标签名"):
        ele = self.wait_ele_presence(locator, center, timeout, doc)
        try:
            tag_name = ele.tag_name
            Logger.info("{}-元素{}的标签名-{}".format(doc, locator, tag_name))
            return tag_name
        except:
            Logger.exception("{}-元素获取标签名失败-{}".format(doc, locator))
            self.save_screenshot("{}-获取标签名失败".format(doc))
            raise

    # iframe处理
    def switch_iframe(self, iframe_reference, timeout=60, doc=""):
        """"""
        try:
            start = datetime.datetime.now()
            WebDriverWait(self.driver, timeout).until(EC.frame_to_be_available_and_switch_to_it(iframe_reference))
            end = datetime.datetime.now()
            Logger.info("{}-进入表单，等待{}秒".format(doc, (end - start).seconds))
        except:
            Logger.exception("{}-进入表单失败-{}".format(doc, iframe_reference))
            self.save_screenshot("{}-进入表单失败".format(doc))
            raise

    # 退回上层表单
    def switch_parent_iframe(self, doc="退回上层表单"):
        self.driver.switch_to.parent_frame()
        Logger.info(doc)

    # 退回初始表单
    def switch_default_iframe(self, doc="退回初始表单"):
        self.driver.switch_to.default_content()
        Logger.info(doc)

    # 刷新页面
    def page_refresh(self, doc="刷新页面"):
        self.driver.refresh()
        # driver.execute_script("location.reload()")
        Logger.info(doc)

    # 等待元素出现再消失
    def wait_ele_gone(self, locator, timeout=15, poll_frequency=0.5, doc=""):
        try:
            start = datetime.datetime.now()
            WebDriverWait(self.driver, timeout, poll_frequency).until(EC.presence_of_element_located(locator))
            end = datetime.datetime.now()
            Logger.info("{}-元素{}已存在，等待{}秒".format(doc, locator, (end - start).seconds))
            WebDriverWait(self.driver, timeout, poll_frequency).until_not(EC.presence_of_element_located(locator))
            end = datetime.datetime.now()
            Logger.info("{}-元素{}已消失，等待{}秒".format(doc, locator, (end - start).seconds))
            try:
                self.save_screenshot("{}-成功".format(doc))
            finally:
                return True
        except:
            Logger.exception("{}-元素不消失-{}".format(doc, locator))
            try:
                self.save_screenshot("{}-元素不消失".format(doc))
            finally:
                return False

    # 断言元素文本包含指定值
    def assert_text(self, locator, expect_text, center=True, timeout=60, doc=""):
        try:
            text = self.get_text(locator, center, timeout, doc)
            result = expect_text in text
            Logger.info("{}-元素{}文本预期为{}，实际为{}，用例执行结果为-{}".format(doc, locator, expect_text, text, result))
            try:
                self.save_screenshot("{}-{}".format(doc, result))
            finally:
                return result
        except:
            Logger.exception("{}-获取文本失败，用例执行失败！！！".format(doc))
            return False

#     # 断言元素属性包含指定值
#     def wait_attribute_tobe(self, locator, attribute, expect_value, timeout=60, poll_frequency=0.5, doc=""):
#         try:
#             start = datetime.datetime.now()
#             if attribute == "text":
#                 WebDriverWait(self.driver, timeout, poll_frequency).until(EC.text_to_be_present_in_element(locator, expect_value))
#             else:
#                 WebDriverWait(self.driver, timeout, poll_frequency).until(attribute_tobe(locator, attribute, expect_value))
#             end = datetime.datetime.now()
#             Logger.info(
#                 "{}-元素{}的{}变为{}-成功，等待{}秒".format(doc, locator, attribute, expect_value, (end - start).seconds))
#             try:
#                 self.save_screenshot("{}-成功".format(doc))
#             finally:
#                 return True
#         except:
#             Logger.exception("{}-元素{}的{}变为{}-失败！！！：".format(doc, locator, attribute, expect_value))
#             try:
#                 self.save_screenshot("{}-失败".format(doc))
#             finally:
#                 return False
# 
# 
# class attribute_tobe(object):
# 
#     def __init__(self, locator, attribute, expect_value):
#         self.locator = locator
#         self.attribute = attribute
#         self.expect_value = expect_value
# 
#     def __call__(self, driver):
#         try:
#             element_value = _find_element(driver, self.locator).get_attribute(self.attribute)
#             result = self.expect_value in element_value
#             return result
#         except:
#             return False


# def _find_element(driver, by):
#     try:
#         return driver.find_element(*by)
#     except:
#         raise


if __name__ == '__main__':
    from selenium import webdriver

    driver = webdriver.Chrome()
    driver.get("www.baidu.com")
    test = BasePage(driver)
    # test.
